#pragma once
#include "funcbase.h"

namespace KRPC {

struct Func : public FuncBase
{	//针对返回参数是非void
	int msec;	//接收超时秒数
	Func(COM &com, int timeoutMsec) : FuncBase(com), msec(timeoutMsec) {}
		
	template<typename R, typename ... Args>
	Optional<R> syncCall(std::string funcname, Args&&... args)
	{
		R ret;
		assert(funcname.size() < MAX_RPCNAME_LEN);
		return (send(funcname, RPC_REQ, std::forward<Args>(args)...) 
				&& recv(ret, RPC_REP, msec)) ? Optional<R>(std::move(ret)) : nullptr;
	}

	template<typename ... Args>
	Optional<void> syncCall(std::string funcname, Args&&... args)
	{
		assert(funcname.size() < MAX_RPCNAME_LEN);
		return (send(funcname, RPC_REQ, std::forward<Args>(args)...) && recv(RPC_REP, msec));
	}

	template<typename R, typename ... Args>
	Result<R> asyncCall(std::string funcname, Args&&... args)
	{
		assert(funcname.size() < MAX_RPCNAME_LEN);
		return send(funcname, RPC_REQ, std::forward<Args>(args)...) \
			? Result<R>(std::bind(&FuncBase::recv<R>, this, std::placeholders::_1, RPC_REP, std::placeholders::_2)) \
			: nullptr;
	}

	template<typename ... Args>
	Result<void> asyncCall(std::string funcname, Args&&... args)
	{
		assert(funcname.size() < MAX_RPCNAME_LEN);
		return send(funcname, RPC_REQ, std::forward<Args>(args)...) \
			? Result<void>(std::bind((bool (FuncBase::*)(MsgMode, int)) &FuncBase::recv, this, RPC_REP, std::placeholders::_1)) \
			: nullptr;
	}
};

} //end of namespace KRPC
